﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Xml;

namespace CLInterpreter
{
	class Program
	{
		/////////////////////////////////
		//Locations to find various resources
		public static string ROOT_STRING = BaseDirString();

		private static string BaseDirString()
		{
			String cp = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
			int cmdloc = cp.LastIndexOf(@"DevX");
			if(cmdloc != -1)
			{
				cmdloc = cp.IndexOf(@"\", cmdloc);
			}

			if(cmdloc == -1)
			{
				Console.WriteLine("Cannot move outside of DevX directory!!!");
				System.Environment.Exit(1);
			}

			string rp = cp.Substring(0, cmdloc + 1);
			return rp;
		}

		public static string TEST_DIR = ROOT_STRING + @"Data\Tests";
		public static string DUMP_DIR = ROOT_STRING + @"Data\";
		
		/////////////////////////////////
		//Files for testing and evaluation

		//Simple tests
		public static string FilterMarkSumExe = TEST_DIR + @"\Simple\FilterMarkSumExample\FilterMarkSumExample\bin\Debug\FilterMarkSumExample.exe";
		public static string TListExe = TEST_DIR + @"\Simple\TList\TList\bin\Debug\TList.exe";
		public static string RListExe = TEST_DIR + @"\Simple\RList\RList\bin\Debug\RList.exe";
		public static string TreeExe = TEST_DIR + @"\Simple\Tree\Tree\bin\Debug\Tree.exe";
		public static string MRaytracerExe = TEST_DIR + @"\Simple\MRaytracer\MRaytracer\bin\Debug\MRaytracer.exe";
		public static string LibQuantumExe = TEST_DIR + @"\Simple\LibQuantum\LibQuantum\bin\Debug\LibQuantum.exe";

		public static string StructAndFuncExe = TEST_DIR + @"\Simple\DelegateTests\DelegateTests\bin\Debug\DelegateTests.exe";
		public static string SetAndDictExe = TEST_DIR + @"\Simple\SetAndDict\SetAndDict\bin\Debug\SetAndDict.exe";

		//csolden tests
		public static string BHExe = TEST_DIR + @"\Olden\BH\BH\bin\Debug\BH.exe";
		public static string BiSortExe = TEST_DIR + @"\Olden\BiSort\BiSort\bin\Debug\BiSort.exe";
		public static string Em3dExe = TEST_DIR + @"\Olden\Em3d\Em3d\bin\Debug\Em3d.exe";
		public static string HealthExe = TEST_DIR + @"\Olden\Health\Health\bin\Debug\Health.exe";
		public static string PerimeterExe = TEST_DIR + @"\Olden\Perimeter\Perimeter\bin\Debug\Perimeter.exe";
		public static string PowerExe = TEST_DIR + @"\Olden\Power\Power\bin\Debug\Power.exe";
		public static string TSPExe = TEST_DIR + @"\Olden\TSP\TSP\bin\Debug\TSP.exe";

		//csspec tests
		public static string DBExe = TEST_DIR + @"\Spec\DB\DB\bin\Debug\DB.exe";
		public static string SpecRaytraceExe = TEST_DIR + @"\Spec\SpecRaytracer\SpecRaytracer\bin\Debug\SpecRaytracer.exe";

		//large tests
		public static string LUIndexExe = TEST_DIR + @"\Large\luindex\bin\NLucene.exe";
		public static string LUSearchExe = TEST_DIR + @"\Large\lusearch\bin\NLucene2.exe";
		public static string RunAbsExe = TEST_DIR + @"\Large\HeapAbs\HeapAbs\bin\Debug\HeapAbs.exe";

		private static string SingleFileToAnalyze = FilterMarkSumExe;

		public static void Main(string[] args)
		{
			string exeasm = SingleFileToAnalyze;

			string baseExec = System.IO.Path.GetFileName(exeasm);

			string hs = "*********** " + baseExec + " ***********";
			string hhs = "";
			for(int kk = 0; kk < hs.Length; ++kk)
				hhs += "*";
			Console.WriteLine("\n\n" + hhs + "\n" + hs + "\n");

			System.Diagnostics.Stopwatch timerload = new System.Diagnostics.Stopwatch();
			timerload.Start();

			SimpleIR.IRProgram p = CCITranslator.CCIExtractor.Extract(exeasm, ROOT_STRING);
			p.LoadTypeInfo();
			p.PreProcLinkAndSimplify();

			p.BuildT1T2();

			timerload.Stop();

			if(System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(DUMP_DIR)))
			{
				String fstr = p.ToString();
				Console.WriteLine("Writing Dump.");
				System.IO.File.WriteAllText(System.IO.Path.Combine(DUMP_DIR, "program.dbg"), fstr);
			}
			p.ReportOnProgramMetrics();

			////
			//Default to all logging enabled, might want to change this later
			InterpreterCore.TracingSystem.EnableUseModLogging();
			InterpreterCore.TracingSystem.EnableDataLogging();

			InterpreterCore.GlobalInterpreterState.LoadProg(p, exeasm, DUMP_DIR, DUMP_DIR);

			//do the analysis
			System.Diagnostics.Stopwatch timeranalyze = new System.Diagnostics.Stopwatch();
			timeranalyze.Start();
			InterpreterCore.GlobalInterpreterState.ExecuteMain(args);
			timeranalyze.Stop();

			Console.WriteLine("Normal Termination!");

			//time post processing
			System.Diagnostics.Stopwatch timerpost = new System.Diagnostics.Stopwatch();
			timerpost.Start();

			if(System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(DUMP_DIR)))
			{
				StringBuilder xmlsb = new StringBuilder();
				System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings { Indent = true, OmitXmlDeclaration = true, CloseOutput = true, Encoding = Encoding.UTF8 };

				using(var xw = XmlWriter.Create(xmlsb, settings))
				{
					p.CallGraph.SerializeToDGML(xw, p);
				}

				Console.WriteLine("Writing Resolved Call Graph.");
				System.IO.File.WriteAllText(System.IO.Path.Combine(DUMP_DIR, "callg.dgml"), xmlsb.ToString());
			}

			timerpost.Stop();

			System.Console.WriteLine("Load Time:         " + timerload.Elapsed.TotalSeconds);
			System.Console.WriteLine("Execute Time:      " + timeranalyze.Elapsed.TotalSeconds);
			System.Console.WriteLine("Post Process Time: " + timerpost.Elapsed.TotalSeconds);
		}
	}
}
